home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / DCP.C < prev    next >
C/C++ Source or Header  |  1991-11-23  |  17KB  |  525 lines

  1. /*
  2.    For best results in visual layout while viewing this file, set
  3.    tab stops to every 4 columns.
  4. */
  5.  
  6. /*
  7.    dcp.c
  8.  
  9.    Revised edition of dcp
  10.  
  11.    Stuart Lynne May/87
  12.  
  13.    Copyright (c) Richard H. Lamb 1985, 1986, 1987
  14.    Changes Copyright (c) Stuart Lynne 1987
  15.    Changes Copyright (c) Andrew H. (Drew) Derbyshire 1989, 1990
  16.  
  17.    Maintenance Notes:
  18.  
  19.    25Aug87 - Added a version number - Jal
  20.    25Aug87 - Return 0 if contact made with host, or 5 otherwise.
  21.    04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup.
  22.    13May89 - Add date to version message  - Drew Derbyshire
  23.    17May89 - Add '-u' (until) option for login processing
  24.    01 Oct 89      Add missing function prototypes                    ahd
  25.    28 Nov 89      Add parse of incoming user id for From record      ahd
  26.    18 Mar 90      Change checktime() calls to Microsoft C 5.1        ahd
  27. */
  28.  
  29. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  30.  
  31. /*
  32.    This program implements a uucico type file transfer and remote
  33.    execution protocol.
  34.  
  35.    Usage:   uuio [-s sys] [-r 0|1] [-x debug]
  36.  
  37.    e.g.
  38.  
  39.    uuio [-x n] -r 0 [-u time]    client mode, wait for an incoming call
  40.              until 'time'.
  41.    uuio [-x n] -s HOST     call the host "HOST".
  42.    uuio [-x n] -s all      call all known hosts in the systems file.
  43.    uuio [-x n] -s any      call any host we have work queued for.
  44.    uuio [-x n]          same as the above.
  45. */
  46.  
  47. #include <stdio.h>                                                /* ahd   */
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <sys/types.h>
  51.  
  52. /*--------------------------------------------------------------------*/
  53. /*                      UUPC/extended prototypes                      */
  54. /*--------------------------------------------------------------------*/
  55.  
  56. #include "lib.h"
  57. #include "arpadate.h"
  58. #include "checktim.h"
  59. #include "dcp.h"
  60. #include "dcplib.h"
  61. #include "dcpstats.h"
  62. #include "dcpsys.h"
  63. #include "dcpxfer.h"
  64. #include "getopt.h"
  65. #include "hlib.h"
  66. #include "hostable.h"
  67. #include "hostatus.h"
  68. #include "modem.h"
  69. #include "security.h"
  70. #include "ssleep.h"
  71.  
  72. /*--------------------------------------------------------------------*/
  73. /*    Define passive and active polling modes; passive is             */
  74. /*    sometimes refered to as "slave", "active" as master.  Since     */
  75. /*    the roles can actually switch during processing, we avoid       */
  76. /*    the terms here                                                  */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. typedef enum {
  80.       POLL_PASSIVE = 0,       /* We answer the telephone          */
  81.       POLL_ACTIVE  = 1        /* We call out to another host      */
  82.       } POLL_MODE ;
  83.  
  84. /*--------------------------------------------------------------------*/
  85. /*                          Global variables                          */
  86. /*--------------------------------------------------------------------*/
  87.  
  88. size_t pktsize;         /* packet size for this protocol*/
  89. FILE *xfer_stream = NULL;        /* stream for file being handled    */
  90. boolean callnow = FALSE;           /* TRUE = ignore time in L.SYS        */
  91. FILE *fwork = NULL, *fsys= NULL ;
  92. FILE *syslog = NULL;
  93. char workfile[FILENAME_MAX];  /* name of current workfile         */
  94. char *Rmtname = nil(char);    /* system we want to call           */
  95. char rmtname[20];             /* system we end up talking to      */
  96. char s_systems[FILENAME_MAX]; /* full-name of systems file        */
  97. struct HostTable *hostp;
  98. struct HostStats remote_stats; /* host status, as defined by hostatus */
  99.  
  100. static boolean dialed = FALSE;/* True = We attempted a phone call */
  101.  
  102. currentfile();
  103.  
  104. /*--------------------------------------------------------------------*/
  105. /*                     Local function prototypes                      */
  106. /*--------------------------------------------------------------------*/
  107.  
  108. static CONN_STATE process( const POLL_MODE poll_mode );
  109.  
  110. static void cant(char *file);
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*    d c p m a i n                                                   */
  114. /*                                                                    */
  115. /*    main program for DCP, called by uuhost                          */
  116. /*--------------------------------------------------------------------*/
  117.  
  118. int dcpmain(int argc, char *argv[])
  119. {
  120.    boolean  Contacted = FALSE;
  121.    int option;
  122.    int poll_mode = POLL_ACTIVE;   /* Default = dial out to system     */
  123.    char *logintime = nil(char);  /* Length of time to wait for login */
  124.  
  125.    char *hotuser = NULL;
  126.    BPS  hotbaud = 0;
  127.  
  128.    fwork = nil(FILE);
  129.  
  130. /*--------------------------------------------------------------------*/
  131. /*                        Process our options                         */
  132. /*--------------------------------------------------------------------*/
  133.  
  134.    while ((option = getopt(argc, argv, "r:s:u:w:x:z:n?")) != EOF)
  135.       switch (option) {
  136.       case 'n':
  137.          callnow = TRUE;
  138.          break;
  139.       case 'r':
  140.          poll_mode = atoi(optarg);
  141.          break;
  142.       case 's':
  143.          Rmtname = strdup(optarg);
  144.          break;
  145.       case 'u':
  146.          logintime = strdup(optarg);
  147.          break;
  148.       case 'x':
  149.          debuglevel = atoi(optarg);
  150.          break;
  151.       case 'z':
  152.          hotbaud = atoi(optarg);
  153.          break;
  154.       case 'w':
  155.          poll_mode = 0;       /* Presume passive polling */
  156.          hotuser = optarg;
  157.          break;
  158.       case '?':
  159.          puts("\nUsage:\tuucico [-s sys] [-r 1|0]\
  160.  [-x debug] [-u time] [-n] [-w user] [-z bps]");
  161.          return 4;
  162.       }
  163.  
  164. /*--------------------------------------------------------------------*/
  165. /*                Abort if any options were left over                 */
  166. /*--------------------------------------------------------------------*/
  167.  
  168.    if (optind != argc) {
  169.       puts("Extra parameter(s) at end.");
  170.       return 4;
  171.    }
  172.  
  173.    if (Rmtname == nil(char))
  174.       Rmtname = "any";
  175.  
  176. /*--------------------------------------------------------------------*/
  177. /*        Initialize logging and the name of the systems file         */
  178. /*--------------------------------------------------------------------*/
  179.  
  180.    if ((logfile = FOPEN(LOGFILE, "a", TEXT)) == nil(FILE))
  181.       cant(LOGFILE);
  182.  
  183.    if (bflag[F_SYSLOG])
  184.    {
  185.       if ((syslog = FOPEN(SYSLOG, "a", TEXT)) == nil(FILE))
  186.          cant(SYSLOG);
  187.    } /* if (bflag[F_SYSLOG]) */
  188.  
  189. /*--------------------------------------------------------------------*/
  190. /* logecho = ((poll_mode == POLL_ACTIVE) ? TRUE : FALSE);             */
  191. /*--------------------------------------------------------------------*/
  192.  
  193.    logecho = TRUE;            /* ahd - One too many missed messages  */
  194.  
  195.  
  196.    mkfilename(s_systems, confdir, SYSTEMS);
  197.    printmsg(2, "Using system file '%s'",s_systems);
  198.  
  199. /*--------------------------------------------------------------------*/
  200. /*              Load connection stats for previous runs               */
  201. /*--------------------------------------------------------------------*/
  202.  
  203.    HostStatus();
  204.  
  205. /*--------------------------------------------------------------------*/
  206. /*                        Initialize security                         */
  207. /*--------------------------------------------------------------------*/
  208.  
  209.    if ( !LoadSecurity())
  210.    {
  211.       printmsg(0,"Unable to initialize security, see previous message");
  212.       panic();
  213.    }
  214.  
  215. /*--------------------------------------------------------------------*/
  216. /*                     Begin main processing loop                     */
  217. /*--------------------------------------------------------------------*/
  218.  
  219.    if (poll_mode == POLL_ACTIVE) {
  220.  
  221.       CONN_STATE m_state = CONN_INITIALIZE;
  222.  
  223.       printmsg(2, "calling \"%s\", debug=%d", Rmtname, debuglevel);
  224.  
  225.       if ((fsys = FOPEN(s_systems, "r", TEXT)) == nil(FILE))
  226.          exit(FAILED);
  227.  
  228.       while (m_state != CONN_EXIT )
  229.       {
  230.          printmsg(4, "M state = %c", m_state);
  231.          switch (m_state)
  232.          {
  233.             case CONN_INITIALIZE:
  234.                m_state = getsystem();
  235.                break;
  236.  
  237.             case CONN_CALLUP:
  238.                dialed = TRUE;
  239.                m_state = callup();
  240.                break;
  241.  
  242.             case CONN_PROTOCOL:
  243.                m_state = startup_server();
  244.                break;
  245.  
  246.             case CONN_SERVER:
  247.                m_state = process( poll_mode );
  248.                Contacted = TRUE;
  249.                break;
  250.  
  251.             case CONN_TERMINATE:
  252.                m_state = sysend();
  253.                break;
  254.  
  255.             case CONN_DROPLINE:
  256.                shutdown();
  257.                m_state = CONN_INITIALIZE;
  258.  
  259.             case CONN_EXIT:
  260.                break;
  261.  
  262.             default:
  263.                printmsg(0,"dcpmain: Unknown master state = %c",m_state );
  264.                panic();
  265.                break;
  266.          } /* switch */
  267.       } /* while */
  268.       fclose(fsys);
  269.  
  270.    }
  271.    else { /* client mode */
  272.  
  273.       CONN_STATE s_state = CONN_INITIALIZE;
  274.  
  275.       if (logintime != NULL)
  276.       {
  277.          if (!checktime(logintime,(time_t) 0))
  278.             printmsg(1,"dcpmain: awaiting login window %s",logintime);
  279.  
  280.          while(!checktime(logintime,(time_t) 0) )  /* Wait for window   */
  281.                  ssleep(60);                   /* Checking one per minute    */
  282.  
  283.          printmsg(2,"Enabling %s for remote login until '%s'",
  284.                     E_inmodem, logintime);
  285.       }
  286.  
  287.       while (s_state != CONN_EXIT )
  288.       {
  289.          printmsg(4, "S state = %c", s_state);
  290.          switch (s_state) {
  291.             case CONN_INITIALIZE:
  292.                if ( hotuser == NULL )
  293.                   s_state = CONN_ANSWER;
  294.                else
  295.                   s_state = CONN_HOTMODEM;
  296.                break;
  297.  
  298.             case CONN_ANSWER:
  299.                s_state = callin( logintime  );
  300.                break;
  301.  
  302.             case CONN_HOTMODEM:
  303.                s_state = callhot( hotbaud );
  304.                break;
  305.  
  306.             case CONN_HOTLOGIN:
  307.                s_state = loginbypass( hotuser );
  308.                break;
  309.  
  310.             case CONN_LOGIN:
  311.                s_state = login();
  312.                break;
  313.  
  314.             case CONN_PROTOCOL:
  315.                s_state = startup_client();
  316.                break;
  317.  
  318.             case CONN_CLIENT:
  319.                Contacted = TRUE;
  320.                s_state = process( poll_mode );
  321.                break;
  322.  
  323.             case CONN_TERMINATE:
  324.                s_state = sysend();
  325.                break;
  326.  
  327.             case CONN_DROPLINE:
  328.                shutdown();
  329.                s_state = CONN_EXIT;
  330.  
  331.             case CONN_EXIT:
  332.                break;
  333.  
  334.             default:
  335.                printmsg(0,"dcpmain: Unknown slave state = %c",s_state );
  336.                panic();
  337.                break;
  338.          } /* switch */
  339.       } /* while */
  340.    } /* else */
  341.  
  342. /*--------------------------------------------------------------------*/
  343. /*                         Report our results                         */
  344. /*--------------------------------------------------------------------*/
  345.  
  346.    if (!Contacted)
  347.    {
  348.       if (dialed)
  349.          printmsg(0, "Could not connect to remote system.");
  350.       else
  351.          printmsg(0, "No work for requested system or wrong time to call.");
  352.    }
  353.  
  354.    dcupdate();
  355.  
  356.    fclose(logfile);
  357.    logfile = stdout;
  358.  
  359.    if (bflag[F_SYSLOG])
  360.       fclose(syslog);
  361.  
  362.    return Contacted ? 0 : 5;
  363.  
  364. } /*dcpmain*/
  365.  
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*    p r o c e s s                                                   */
  369. /*                                                                    */
  370. /*    The procotol state machine                                      */
  371. /*--------------------------------------------------------------------*/
  372.  
  373. static CONN_STATE process( const POLL_MODE poll_mode )
  374. {
  375.    boolean master;
  376.    XFER_STATE state = ( poll_mode == POLL_ACTIVE ) ? XFER_SENDINIT :
  377.                                                      XFER_RECVINIT;
  378.    XFER_STATE old_state = XFER_EXIT;
  379.                               /* Initialized to any state but the
  380.                                  original value of "state"           */
  381.    XFER_STATE save_state = XFER_EXIT;
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*  Yea old state machine for the high level file transfer procotol   */
  385. /*--------------------------------------------------------------------*/
  386.  
  387.    while( state != XFER_EXIT )
  388.    {
  389.       printmsg(state == old_state ? 14 : 4 ,
  390.                "process: Machine state is = %c", state );
  391.       old_state = state;
  392.  
  393.       switch( state )
  394.       {
  395.  
  396.          case XFER_SENDINIT:  /* Initialize outgoing protocol        */
  397.             state = sinit();
  398.             break;
  399.  
  400.          case XFER_RECVINIT:  /* Initialize Receive protocol         */
  401.             state = rinit();
  402.             break;
  403.  
  404.          case XFER_MASTER:    /* Begin master mode                   */
  405.             master = TRUE;
  406.             state = XFER_NEXTJOB;
  407.             break;
  408.  
  409.          case XFER_SLAVE:     /* Begin slave mode                    */
  410.             master = FALSE;
  411.             state = XFER_RECVHDR;
  412.             break;
  413.  
  414.          case XFER_NEXTJOB:   /* Look for work in local queue        */
  415.             state = scandir( rmtname );
  416.             break;
  417.  
  418.          case XFER_REQUEST:   /* Process next file in current job
  419.                                  in queue                            */
  420.             state = newrequest();
  421.             break;
  422.  
  423.          case XFER_PUTFILE:   /* Got local tranmit request           */
  424.             state = ssfile();
  425.             break;
  426.  
  427.          case XFER_GETFILE:   /* Got local tranmit request           */
  428.             state = srfile();
  429.             break;
  430.  
  431.          case XFER_SENDDATA:  /* Remote accepted our work, send data */
  432.             state = sdata();
  433.             break;
  434.  
  435.          case XFER_SENDEOF:   /* File xfer complete, send EOF        */
  436.             state = seof( master );
  437.             break;
  438.  
  439.          case XFER_FILEDONE:  /* Receive or transmit is complete     */
  440.             state = master ? XFER_REQUEST : XFER_RECVHDR;
  441.             break;
  442.  
  443.          case XFER_NOLOCAL:   /* No local work, remote have any?     */
  444.             state = sbreak();
  445.             break;
  446.  
  447.          case XFER_NOREMOTE:  /* No remote work, local have any?     */
  448.             state = schkdir( poll_mode == POLL_ACTIVE );
  449.             break;
  450.  
  451.          case XFER_RECVHDR:   /* Receive header from other host      */
  452.             state = rheader();
  453.             break;
  454.  
  455.          case XFER_TAKEFILE:  /* Set up to receive remote requested
  456.                                  file transfer                       */
  457.             state = rrfile();
  458.             break;
  459.  
  460.          case XFER_GIVEFILE:  /* Set up to transmit remote
  461.                                  requuest file transfer              */
  462.             state = rsfile();
  463.             break;
  464.  
  465.          case XFER_RECVDATA:  /* Receive file data from other host   */
  466.             state = rdata();
  467.             break;
  468.  
  469.          case XFER_RECVEOF:
  470.             state = reof();
  471.             break;
  472.  
  473.          case XFER_LOST:      /* Lost the other host, flame out      */
  474.             printmsg(0,"process: Connection lost to %s, \
  475. previous system state = %c", rmtname, save_state );
  476.             state = XFER_EXIT;
  477.             break;
  478.  
  479.          case XFER_ABORT:     /* Internal error, flame out           */
  480.             printmsg(0,"process: Aborting connection to %s, \
  481. previous system state = %c", rmtname, save_state );
  482.             state = XFER_ENDP;
  483.             break;
  484.  
  485.          case XFER_ENDP:      /* Terminate the protocol              */
  486.             state = endp();
  487.             break;
  488.  
  489.          default:
  490.             printmsg(0,"process: Unknown state = %c, \
  491. previous system state = %c", state, save_state );
  492.             state = XFER_ABORT;
  493.             break;
  494.       } /* switch */
  495.       save_state = old_state; /* Used only if we abort               */
  496.    } /* while( state != XFER_EXIT ) */
  497.  
  498. /*--------------------------------------------------------------------*/
  499. /*                        Update system status                        */
  500. /*--------------------------------------------------------------------*/
  501.  
  502.    dcstats();
  503.  
  504. /*--------------------------------------------------------------------*/
  505. /*           Protocol is complete, terminate the connection           */
  506. /*--------------------------------------------------------------------*/
  507.  
  508.    return CONN_TERMINATE;
  509.  
  510. } /* process */
  511.  
  512. /*--------------------------------------------------------------------*/
  513. /*    c a n t                                                         */
  514. /*                                                                    */
  515. /*    report that we cannot open a critical file                      */
  516. /*--------------------------------------------------------------------*/
  517.  
  518. static void cant(char *file)
  519. {
  520.  
  521.    fprintf(stderr, "Can't open: \"%s\"\n", file);
  522.    perror( file );
  523.    panic();
  524. } /*cant*/
  525.